package com.zhx.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.util.AttributeKey;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;

/**
 * @author zhanghaixuan
 * @version 1.0
 * date 2021/5/20-10:18 上午
 * description netty服务端
 */
public class NettyServer {

    public static void main(String[] args) {
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        /**
         * 对应NIO里面的 serverchannel 负责接活
         */
        NioEventLoopGroup boss = new NioEventLoopGroup();
        /**
         * 对应NIO里面的clientchannel 负责处理实际的工作
         */
        NioEventLoopGroup worker = new NioEventLoopGroup();
        serverBootstrap
                //绑定 老板和工人
                .group(boss, worker)
                .channel(NioServerSocketChannel.class)
                //服务端启动时候的逻辑
                .handler(new ChannelInitializer<NioServerSocketChannel>() {
                    @Override
                    protected void initChannel(NioServerSocketChannel ch) throws Exception {
                        System.out.printf("服务启动中");
                    }
                })
                //给每一条连接指定自定义属性
                .childAttr(AttributeKey.newInstance("value"), "value")
                //给每条连接设置一些底层相关的东西
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .childOption(ChannelOption.TCP_NODELAY, true)
                //给服务端进行一些配置
                .option(ChannelOption.SO_BACKLOG, 1024)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel ch) {
                        ch.pipeline().addLast(new StringDecoder());
                        ch.pipeline().addLast(new SimpleChannelInboundHandler<String>() {
                            @Override
                            protected void channelRead0(ChannelHandlerContext ctx, String msg) {
                                System.out.println(msg);
                            }
                        });
                    }
                });
                bind(serverBootstrap,1000);
    }


    private static void bind(ServerBootstrap bootstrap,final int port){
        bootstrap                .bind(8000).addListener(new GenericFutureListener<Future<? super Void>>() {
            @Override
            public void operationComplete(Future<? super Void> future) throws Exception {
                if (future.isSuccess()) {
                    System.out.printf("端口["+port+"]绑定成功");
                }else{
                    System.out.printf("端口["+port+"]绑定失败");
                    bind(bootstrap,port+1);
                }
            }
        });
    }
}
